package server;
import edu.stanford.nlp.classify.ColumnDataClassifier;
import org.ansj.domain.Result;
import org.ansj.domain.Term;
import org.ansj.library.DicLibrary;
import org.ansj.splitWord.analysis.NlpAnalysis;
import org.ansj.splitWord.analysis.ToAnalysis;
import org.ansj.util.MyStaticValue;
import org.nlpcn.commons.lang.tire.domain.Forest;
import org.nlpcn.commons.lang.tire.library.Library;
import sluentities.ClassifierResult;

import java.io.*;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * Created by sunjia on 2018/1/10.
 * stanford.nlp的接口类
 */

public class MaxEntClassifier {

    String path_prop; //配置文件地址
    String path_model; //model地址
    ColumnDataClassifier cdc; //分类器
    ToAnalysis analysis; //分词
    Forest forest; // 用户词典


    public MaxEntClassifier() {

        this.path_prop = MaxEntClassifier.class.getClassLoader().getResource("classifier.prop").getPath();
        this.path_model = MaxEntClassifier.class.getClassLoader().getResource("model.bin").getPath();
        cdc = new ColumnDataClassifier(path_prop, path_model);
        analysis = new ToAnalysis();
        try {
            forest=Library.makeForest(MaxEntClassifier.class.getResourceAsStream("/library/default.dic"));//加载字典文件
        } catch (Exception e) {
            e.printStackTrace();
        }
        analysis.setForests(forest);
        analysis.parseStr("");//分词提速
    }


    public void maxentTrain(String trainFile, String serializeTo){
        try {
            cdc.trainClassifier(trainFile, serializeTo);
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("训练失败");
        }

    }

//    测试line
    public List<ClassifierResult> maxentPredict(String line) {

        List<ClassifierResult> classifierResults = new ArrayList<>();
        try {

            classifierResults = cdc.predict(line);//分类器耗时仅5ms
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("预测失败");
            return classifierResults;//分类器出错时返回一个空的classifierResults
        }
        return classifierResults;
    }

    //ANSJ分词
    public String segment(String line) throws Exception {

        String lineSeged = "";
        Result result = analysis.parse(line, forest);
        List<Term> termList = result.getTerms();
        for(Term term : termList){
            if (!term.getNatureStr().contains("w")){//过滤标点符号
                lineSeged += term.getName() + " ";
            }
        }
        lineSeged = lineSeged.trim();
        return lineSeged;

    }

    //将数据合成txt，并送入分类器训练Model
    public void train(String path_corpus, String path_traindata) throws Exception {

        //step1 组织训练数据成一个分词后TXT
        HashSet<String> outTrain = new HashSet<String>() {{//不参与训练的command列表
            add("command@简短词");
            add("command@敏感词");
            add("command@其他业务");
            add("command@闲聊类");
            add("command@业务咨询");
        }};
        OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(path_traindata,false),"UTF-8");
        File file = new File(path_corpus);
        File[] files = file.listFiles();// 获取目录下的所有文件或文件夹
        for (File f : files) {
            String filename = f.getName();
            if (f.isFile() && !outTrain.contains(filename)) {
                InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream(f), "utf-8");
                BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
                String label = f.getName();
                String line = "";
                String lineSeged = "";
                while ((line = bufferedReader.readLine()) != null) {
                    lineSeged = segment(line);
                    writer.write(label + "\t" + lineSeged + "\n");
                }
            }
        }
        writer.close();
        //step2 送入分类器，生成model
        maxentTrain(path_traindata, path_model);

    }

    public List<ClassifierResult> predict(String input) throws Exception {

        List<ClassifierResult> results = new ArrayList<>();
        String inputSeged = segment(input);
        List<ClassifierResult> classifierResults = maxentPredict("test"+"\t"+inputSeged);
        for (ClassifierResult c : classifierResults) {
            ClassifierResult result= new ClassifierResult();
            result.setScore(c.getScore());
            result.setAnswer(c.getAnswer());
            results.add(result);
        }
        return results;
    }

    public static void main(String[] args) throws Exception {

        MaxEntClassifier classifier = new MaxEntClassifier();
        System.out.println(classifier.path_model);
//        System.out.println(classifier.new_path_model);
//        System.out.println(classifier.path_tmp);
        classifier.predict("1\t话费");
    }


}
